<?php

namespace app\models;

use Yii;
use app\components\Fun;
use app\models\Error;
/**
 * This is the model class for table "{{%token}}".
 *
 * @property string $id
 * @property string $name
 * @property string $val
 */
class Token extends \yii\db\ActiveRecord
{
    
    
      public $appid;
      public $appsecret;
    
       
       public $error=false;
       
       
       
       public function __set($name, $value) {
           
             if(in_array($name, $this->lab)){
              $this->set_val($name,$value);
               $this->_data[$name]=$value;
              return $value;
            }
           
           Yii::$app->cache->delete('Token');
           return parent::__set($name, $value);
       }
      
       public $lab=[
           'weixin_access_token',
           'weixin_access_token_time',
           'jsapi_ticket',
           'jsapi_ticket_time'
       ];
       
       private $_data=[];

       
       
       /**
        * 从缓存中或者数据库取出数据
       */
      private function get_data(){
          $cache=Yii::$app->cache->get('Token');
          //var_dump($cache);
          if($cache===false){
             
              $cache=[];
              foreach ($this->lab as $vo){
                  ///echo '******'.$vo;
                  $cache[$vo]=$this->get_val($vo);
                   //print_r($this->get_val($key));//exit;
              }
              Yii::$app->cache->set('Token',$cache,60);
  
          }
           return $cache;
      }

      public function __get($name) {
           
       //// echo '{';  print_r($this->_data);echo '}';
           
           if(in_array($name, $this->lab)){
             
               if($this->_data===[]){
                  $this->_data=$this->get_data(); 
               }
               
            
               
               if(isset($this->_data[$name])){
                     
                   return $this->_data[$name];
               }else{
                   return false;
               }
              /* $this->$name=$this->get_val($name);
               return $this->_data[$name];*/
           }
           
           return parent::__get($name);
       }
       
       private function get_val($key){
  ///        $key='fdsa';
         $model=$this->find()->where([
               'name'=>$key
           ])->select('val')->one();
  
           if($model===null){
               return false;
           }else{
               return $model->val;
           }
       }

       /**
        * 保存项目值
      
      private function up_save(){
          $this->set_val('weixin_access_token',$this->weixin_access_token);
          $this->set_val('weixin_access_token_time',$this->weixin_access_token_time);
          $this->set_val('jsapi_ticket',$this->jsapi_ticket);
          $this->set_val('jsapi_ticket_time',$this->jsapi_ticket_time);
      }
       */
      /**
       * 保存值
      */
     private function set_val($name,$val){
         
       ///  echo '修改set_val:'.$name.':'.$val; echo '<br>';
          
         
          $model=$this->find()->where([
               'name'=>$name
           ])->one();
         
  
           if($model===null){
               $model=new Token();
               $model->name=$name;
               $model->val=$val;
               $model->save();
           }else{
            
           $model->val=$val;
           $model->update();
        }
     }


       
       
        public function get_weixin_access_token(){
          
       
            
            if($this->weixin_access_token==''||$this->weixin_access_token_time==''||$this->weixin_access_token_time<=time()){
                 if($this->up_weixin_access_token()===false){
                     return false;
                 }
            }
            return $this->weixin_access_token;
        }
        
     ////   public $jsapi_ticket;
      ///  public $jsapi_ticket_time;


        public function getJsApiTicket(){
       
          ///  $this->load_init();
          ////  var_dump($this->jsapi_ticket==''||$this->jsapi_ticket_time==''||$this->jsapi_ticket_time<=time());
             if($this->jsapi_ticket==''||$this->jsapi_ticket_time==''||$this->jsapi_ticket_time<=time()){
                
               if(!$this->up_jsapi_ticket()) return false;
            }
            return $this->jsapi_ticket;
        }
        
        
        
        /**
         * 重置
        */
        public function chongzhi(){
            $this->deleteAll();
            $this->_data=[];
        }

        /***/
        private function up_jsapi_ticket(){
            $acc=$this->get_weixin_access_token();
            if($acc===false){
                return false;
            }
            $url='https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='
                 .$acc.'&type=jsapi';
             $data = Fun::curl_get($url, '');
              
              $json = json_decode($data, true);
              
                Error::addmsg('开始获取jsapi_ticket:获取新的:'.print_r($json,true).'旧版本:jsapi_ticket:'.$this->jsapi_ticket.',jsapi_ticket_time:'.$this->jsapi_ticket_time,  Error::Err_putong);
              
              
              if($json['errcode']!==0){///出错了,重置一次,从新调用一次up_jsapi_ticket,然后再试一次
                  
                  if($this->error){///如果第一次已经是错误了,那么这次直接返回错误
                      Error::addmsg('第二次调用失败'.print_r($json,true),  Error::Err_putong);
                  }
                  
                  
                  $this->error=true;
                  
                  $this->chongzhi();///重置一次
                  
                  Error::addmsg('首次调用失败,准备调用第二次'.print_r($json,true),  Error::Err_putong);
                 
                  return $this->up_jsapi_ticket();
              }
                 ///   echo $url;   var_dump($json);exit;
                        $this->jsapi_ticket = $json['ticket'];
                        $this->jsapi_ticket_time = $json['expires_in'] + time() - 120;
                       /// $this->up_save();
                        
                     // var_dump( $json, $this->jsapi_ticket, $this->jsapi_ticket_time);exit;
                        
            return true;
    }

        /**
         * 更新access_token
        */
       private function up_weixin_access_token(){
         //  echo 'up_weixin_access_token';
           
            $data=Fun::curl_get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.
            $this->appid.'&secret='.
            $this->appsecret,'');
            $json=  json_decode($data,true);
            //var_dump($json);exit;
             if(isset($json['errcode'])&&$json['errcode']!==0){///出错了 保存错误信息
                 Error::addmsg('获取access_token出错了'.print_r($json,true),  Error::Err_putong);
               ///  Error::adderrormsg('获取access_token出错了'.print_r($json,true));
                 return false;
             }
           /// var_dump($json);exit;
   // Error::addmsg('access_token:获取新的:'.
   //         print_r($json,true).'旧版本:weixin_access_token:'.$this->weixin_access_token.
   //         ',weixin_access_token_time:'.$this->weixin_access_token_time,  Error::Err_putong);
              
            $this->weixin_access_token=$json['access_token'];
            $this->weixin_access_token_time=$json['expires_in']+time()-120;
            return true;
            ///var_dump($json);exit;
        //    $this->up_save(); 
       }
       
       
       
       
       public static function GetSignPackage($th){
           $model=new Token;
           
           
       $model->appid=$th->appId;
       $model->appsecret=$th->appsecret;
           
           $jsapiTicket = $model->getJsApiTicket();
           
         ///  echo $jsapiTicket;exit;
           
           if($jsapiTicket===false){
              return false; 
           }
          
    // 注意 URL 一定要动态获取，不能 hardcode.
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
        $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

        
        
        $timestamp = time();
        $nonceStr = $model->createNonceStr();

        
       
        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
   
        $signature = sha1($string);
 
       return array(
            "appId" => $model->appid,
            "nonceStr" => $nonceStr,
            "timestamp" => $timestamp,
            "url" => $url,
            "signature" => $signature,
            "rawString" => $string
        );
        
      ///  print_r($signPackage);exit;
    }
   
       
    
    /**
     * 使用引用的域名地址
    */
    public static function GetSignPackage_HOST_URL($th){
           $model=new Token;           
       $model->appid=$th->appId;
       $model->appsecret=$th->appsecret;           
           $jsapiTicket = $model->getJsApiTicket();     
           
     
           if($jsapiTicket===false){
              return false; 
           } 
    // 注意 URL 一定要动态获取，不能 hardcode.
 
        
           if(!empty($_SERVER['HTTP_REFERER'])){
                  $url=$_SERVER['HTTP_REFERER']; 
           }else{
                $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
                 $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; 
           }
         
        $timestamp = time();
        $nonceStr = $model->createNonceStr();      
        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";   
        $signature = sha1($string); 
       return array(
            "appId" => $model->appid,
            "nonceStr" => $nonceStr,
            "timestamp" => $timestamp,
            "url" => $url,
            "signature" => $signature,
            "rawString" => $string
        );
    }
    
    
    private function createNonceStr($length = 16) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%token}}';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
          ///  [['name'], 'string', 'max' => 1024],
          ///   [['val'], 'string', 'max' => 1024],
              [['name','val'],'safe']
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'name' => 'Name',
            'val' => 'Val',
        ];
    }
}
